home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
djgpp
/
clients
/
xfd
/
fontgrid.c
next >
Wrap
Text File
|
1994-08-12
|
17KB
|
547 lines
/*
* $XConsortium: fontgrid.c,v 1.25 91/07/18 14:59:57 rws Exp $
*
* Copyright 1989 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. M.I.T. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Jim Fulton, MIT X Consortium
*/
#ifdef MSDOS
#include "X11/IntrinsP.h" /* QDK 05/12/1994 2:28pm. */
#else
#include "X11/IntrinsicP.h"
#endif
#include <X11/StringDefs.h>
#include <X11/Xaw/SimpleP.h>
#include <X11/Xmu/Converters.h>
#ifdef MSDOS
#include "fontgrip.h"
#else
#include "fontgridP.h"
#endif
#define Bell(w) XBell(XtDisplay(w), 50)
static void ClassInitialize(), Initialize(), Realize(), Redisplay(), Notify();
static void Destroy(), Resize(), paint_grid();
static Boolean SetValues();
#define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field)
static XtResource resources[] = {
{ XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
Offset(text_font), XtRString, (XtPointer) NULL },
{ XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int),
Offset(cell_cols), XtRImmediate, (XtPointer) 0 },
{ XtNcellRows, XtCCellRows, XtRInt, sizeof(int),
Offset(cell_rows), XtRImmediate, (XtPointer) 0 },
{ XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int),
Offset(cell_width), XtRImmediate, (XtPointer) 0 },
{ XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int),
Offset(cell_height), XtRImmediate, (XtPointer) 0 },
{ XtNstartChar, XtCStartChar, XtRDimension, sizeof(Dimension),
Offset(start_char), XtRImmediate, (XtPointer) 0xffff },
{ XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground },
{ XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean),
Offset(center_chars), XtRImmediate, (XtPointer) FALSE },
{ XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean),
Offset(box_chars), XtRImmediate, (XtPointer) FALSE },
{ XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel),
Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground },
{ XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
Offset(callbacks), XtRCallback, (XtPointer) NULL },
{ XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int),
Offset(internal_pad), XtRImmediate, (XtPointer) 4 },
{ XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int),
Offset(grid_width), XtRImmediate, (XtPointer) 1 },
};
#undef Offset
static char defaultTranslations[] =
"<ButtonPress>: notify()";
static XtActionsRec actions_list[] = {
{ "notify", Notify },
};
FontGridClassRec fontgridClassRec = {
{ /* core fields */
/* superclass */ (WidgetClass) &simpleClassRec,
/* class_name */ "FontGrid",
/* widget_size */ sizeof(FontGridRec),
/* class_initialize */ ClassInitialize,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ Realize,
/* actions */ actions_list,
/* num_actions */ XtNumber(actions_list),
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
/* resize */ Resize,
/* expose */ Redisplay,
/* set_values */ SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ defaultTranslations,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ XtInheritDisplayAccelerator,
/* extension */ NULL
},
{ /* simple fields */
/* change_sensitive */ XtInheritChangeSensitive
}
};
WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec;
/*
* public routines
*/
void GetFontGridCellDimensions (w, startp, ncolsp, nrowsp)
Widget w;
Dimension *startp;
int *ncolsp, *nrowsp;
{
FontGridWidget fgw = (FontGridWidget) w;
*startp = (long)fgw->fontgrid.start_char;
*ncolsp = fgw->fontgrid.cell_cols;
*nrowsp = fgw->fontgrid.cell_rows;
}
void GetPrevNextStates (w, prevvalidp, nextvalidp)
Widget w;
Bool *prevvalidp, *nextvalidp;
{
FontGridWidget fgw = (FontGridWidget) w;
XFontStruct *fs = fgw->fontgrid.text_font;
long minn = (long) ((fs->min_byte1 << 0) | fs->min_char_or_byte2);
long maxn = (long) ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
*prevvalidp = ((long)fgw->fontgrid.start_char > minn);
*nextvalidp = (((long)fgw->fontgrid.start_char +
(fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows))
< maxn);
}
/*
* private routines and methods
*/
static GC get_gc (fgw, fore)
FontGridWidget fgw;
Pixel fore;
{
XtGCMask mask;
XGCValues gcv;
mask = (GCForeground | GCBackground | GCFunction | GCFont);
gcv.foreground = fore;
gcv.background = fgw->core.background_pixel;
gcv.function = GXcopy;
gcv.font = fgw->fontgrid.text_font->fid;
gcv.cap_style = CapProjecting;
mask |= GCCapStyle;
if (fgw->fontgrid.grid_width > 0) {
mask |= GCLineWidth;
gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 :
fgw->fontgrid.grid_width);
}
return (XtGetGC ((Widget) fgw, mask, &gcv));
}
static void ClassInitialize ()
{
XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0);
}
static void Initialize (request, new)
Widget request, new;
{
FontGridWidget reqfg = (FontGridWidget) request;
FontGridWidget newfg = (FontGridWidget) new;
XFontStruct *fs = newfg->fontgrid.text_font;
unsigned maxn;
if (reqfg->fontgrid.cell_cols <= 0)
newfg->fontgrid.cell_cols = 16;
if (reqfg->fontgrid.cell_rows <= 0) {
if (fs && fs->max_byte1 == 0) {
newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 /
newfg->fontgrid.cell_cols) + 1;
if (newfg->fontgrid.cell_rows > 16)
newfg->fontgrid.cell_rows = 16;
} else
newfg->fontgrid.cell_rows = 16;
}
if (reqfg->fontgrid.cell_width <= 0)
newfg->fontgrid.cell_width = (fs ? DefaultCellWidth (newfg) : 1);
if (reqfg->fontgrid.cell_height <= 0)
newfg->fontgrid.cell_height = (fs ? DefaultCellHeight (newfg) : 1);
/* give a nice size that fits one screen full */
if (newfg->core.width == 0)
newfg->core.width = (newfg->fontgrid.cell_width *
newfg->fontgrid.cell_cols +
newfg->fontgrid.grid_width *
(newfg->fontgrid.cell_cols + 1));
if (newfg->core.height == 0)
newfg->core.height = (newfg->fontgrid.cell_height *
newfg->fontgrid.cell_rows +
newfg->fontgrid.grid_width *
(newfg->fontgrid.cell_rows + 1));
/*
* select the first character
*/
if (newfg->fontgrid.start_char == 0xffff) {
newfg->fontgrid.start_char = (fs ? (unsigned)(fs->min_byte1 << 8) : 0);
}
if (fs) {
maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
if (newfg->fontgrid.start_char > maxn)
newfg->fontgrid.start_char = (maxn + 1 -
(newfg->fontgrid.cell_cols *
newfg->fontgrid.cell_rows));
}
}
static void Realize (gw, valueMask, attributes)
Widget gw;
Mask *valueMask;
XSetWindowAttributes *attributes;
{
FontGridWidget fgw = (FontGridWidget) gw;
FontGridPart *p = &fgw->fontgrid;
p->text_gc = get_gc (fgw, p->foreground_pixel);
p->box_gc = get_gc (fgw, p->box_pixel);
Resize (gw);
(*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes);
return;
}
static void Destroy (gw)
Widget gw;
{
FontGridWidget fgw = (FontGridWidget) gw;
XtReleaseGC (gw, fgw->fontgrid.text_gc);
XtReleaseGC (gw, fgw->fontgrid.box_gc);
}
static void Resize (gw)
Widget gw;
{
FontGridWidget fgw = (FontGridWidget) gw;
/* recompute in case we've changed size */
fgw->fontgrid.cell_width = CellWidth (fgw);
if (fgw->fontgrid.cell_width <= 0)
fgw->fontgrid.cell_width = 1;
fgw->fontgrid.cell_height = CellHeight (fgw);
if (fgw->fontgrid.cell_height <= 0)
fgw->fontgrid.cell_height = 1;
fgw->fontgrid.xoff = (fgw->fontgrid.cell_width -
DefaultCellWidth (fgw)) / 2;
fgw->fontgrid.yoff = (fgw->fontgrid.cell_height -
DefaultCellHeight (fgw)) / 2;
}
/* ARGSUSED */
static void Redisplay (gw, event, region)
Widget gw;
XEvent *event;
Region region;
{
FontGridWidget fgw = (FontGridWidget) gw;
XRectangle rect; /* bounding rect for region */
int left, right, top, bottom; /* which cells were damaged */
int cw, ch; /* cell size */
if (!fgw->fontgrid.text_font) {
Bell (gw);
return;
}
/*
* compute the left, right, top, and bottom cells that were damaged
*/
XClipBox (region, &rect);
cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width;
ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width;
if ((left = (((int) rect.x) / cw)) < 0) left = 0;
right = (((int) (rect.x + rect.width - 1)) / cw);
if ((top = (((int) rect.y) / ch)) < 0) top = 0;
bottom = (((int) (rect.y + rect.height - 1)) / ch);
paint_grid (fgw, left, top, right - left + 1, bottom - top + 1);
}
static void paint_grid (fgw, col, row, ncols, nrows)
FontGridWidget fgw; /* widget in which to draw */
int col, row; /* where to start */
int ncols, nrows; /* number of cells */
{
FontGridPart *p = &fgw->fontgrid;
int i, j;
Display *dpy = XtDisplay(fgw);
Window wind = XtWindow(fgw);
int cw = p->cell_width + p->grid_width;
int ch = p->cell_height + p->grid_width;
int tcols = p->cell_cols;
int trows = p->cell_rows;
int x1, y1, x2, y2, x, y;
unsigned maxn = ((p->text_font->max_byte1 << 8) |
p->text_font->max_char_or_byte2);
unsigned n, prevn;
int startx;
if (col + ncols >= tcols) {
ncols = tcols - col;
if (ncols < 1) return;
}
if (row + nrows >= trows) {
nrows = trows - row;
if (nrows < 1) return;
}
/*
* paint the grid lines for the indicated rows
*/
if (p->grid_width > 0) {
int half_grid_width = p->grid_width >> 1;
x1 = col * cw + half_grid_width;
y1 = row * ch + half_grid_width;
x2 = x1 + ncols * cw;
y2 = y1 + nrows * ch;
for (i = 0, x = x1; i <= ncols; i++, x += cw) {
XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2);
}
for (i = 0, y = y1; i <= nrows; i++, y += ch) {
XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y);
}
}
/*
* Draw a character in every box; treat all fonts as if they were 16bit
* fonts. Store the high eight bits in byte1 and the low eight bits in
* byte2.
*/
prevn = p->start_char + col + row * tcols;
startx = col * cw + p->internal_pad + p->grid_width;
for (j = 0,
y = row * ch + p->internal_pad + p->grid_width + p->text_font->ascent;
j < nrows; j++, y += ch) {
n = prevn;
for (i = 0, x = startx; i < ncols; i++, x += cw) {
XChar2b thechar;
int xoff = p->xoff, yoff = p->yoff;
if (n > maxn) goto done; /* no break out of nested */
thechar.byte1 = (n >> 8); /* high eight bits */
thechar.byte2 = (n & 255); /* low eight bits */
if (p->box_chars || p->center_chars) {
XCharStruct metrics;
int direction, fontascent, fontdescent;
XTextExtents16 (p->text_font, &thechar, 1, &direction,
&fontascent, &fontdescent, &metrics);
if (p->center_chars) {
/*
* We want to move the origin by enough to center the ink
* within the cell. The left edge will then be at
* (cell_width - (rbearing - lbearing)) / 2; so we subtract
* the lbearing to find the origin. Ditto for vertical.
*/
xoff = (((p->cell_width -
(metrics.rbearing - metrics.lbearing)) / 2) -
p->internal_pad - metrics.lbearing);
yoff = (((p->cell_height -
(metrics.descent + metrics.ascent)) / 2) -
p->internal_pad -
p->text_font->ascent + metrics.ascent);
}
if (p->box_chars) {
XDrawRectangle (dpy, wind, p->box_gc,
x + xoff, y + yoff - p->text_font->ascent,
metrics.width - 1,
fontascent + fontdescent - 1);
}
}
XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff,
&thechar, 1);
n++;
}
prevn += tcols;
}
done:
return;
}
/*ARGSUSED*/
static Boolean SetValues (current, request, new, args, num_args)
Widget current, request, new;
ArgList args;
Cardinal *num_args;
{
FontGridWidget curfg = (FontGridWidget) current;
FontGridWidget newfg = (FontGridWidget) new;
Boolean redisplay = FALSE;
if (curfg->fontgrid.text_font != newfg->fontgrid.text_font ||
curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) {
newfg->fontgrid.cell_width = DefaultCellWidth (newfg);
newfg->fontgrid.cell_height = DefaultCellHeight (newfg);
redisplay = TRUE;
}
if (curfg->fontgrid.foreground_pixel != newfg->fontgrid.foreground_pixel) {
XtReleaseGC (new, curfg->fontgrid.text_gc);
newfg->fontgrid.text_gc = get_gc (newfg,
newfg->fontgrid.foreground_pixel);
redisplay = TRUE;
}
if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) {
XtReleaseGC (new, curfg->fontgrid.text_gc);
newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel);
redisplay = TRUE;
}
if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars ||
curfg->fontgrid.box_chars != newfg->fontgrid.box_chars)
redisplay = TRUE;
if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) {
XFontStruct *fs = newfg->fontgrid.text_font;
unsigned maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
if (newfg->fontgrid.start_char > maxn)
newfg->fontgrid.start_char = (maxn + 1 -
(newfg->fontgrid.cell_cols *
newfg->fontgrid.cell_rows));
redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char);
}
return redisplay;
}
/* ARGSUSED */
static void Notify (gw, event, params, nparams)
Widget gw;
XEvent *event;
String *params;
Cardinal *nparams;
{
FontGridWidget fgw = (FontGridWidget) gw;
int x, y; /* where the event happened */
FontGridCharRec rec; /* callback data */
/*
* only allow events with (x,y)
*/
switch (event->type) {
case KeyPress:
case KeyRelease:
x = event->xkey.x;
y = event->xkey.y;
break;
case ButtonPress:
case ButtonRelease:
x = event->xbutton.x;
y = event->xbutton.y;
break;
case MotionNotify:
x = event->xmotion.x;
y = event->xmotion.y;
break;
default:
Bell (gw);
return;
}
/*
* compute the callback data
*/
{
int cw = fgw->fontgrid.cell_width, ch = fgw->fontgrid.cell_height;
unsigned n;
if (x > (fgw->fontgrid.cell_cols * cw)) {
Bell (gw);
return;
}
n= (fgw->fontgrid.start_char +
((y / ch) * fgw->fontgrid.cell_cols) + (x / cw));
rec.thefont = fgw->fontgrid.text_font;
rec.thechar.byte1 = (n >> 8);
rec.thechar.byte2 = (n & 255);
}
XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec);
}